using System;
using System.Net;
using CommandLine.Utility;
using System.Collections;
using System.Collections.Generic;
using System.Web.Services.Protocols;
using System.Text;
using System.Security;
using System.IO;
using System.Xml;
using System.Data;
using System.Xml.Serialization;
using FPSEPublish;
using ns;
using System.Text.RegularExpressions;


namespace ConsoleDocEnum
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            Arguments CommandLine = new Arguments(args);
            if (CommandLine != null)
            {

                if (CommandLine["url"] != null)
                {
                    string PDUrl = CommandLine["url"] + "/_vti_bin/";
                    
                    //DISPLAY STRUCTRE OF CURRENT SITE AREA
                    if (CommandLine["structure"] != null)
                    { Console.WriteLine(GetStructure(PDUrl)); }

                    /////////////////////////////////////
                    //ACTIONS FOR CONTENT ARGUMENT
                    if (CommandLine["content"] != null)
                    {
                        Console.WriteLine(ListContent(PDUrl, CommandLine["content"]));
                    }

                    if ((CommandLine["addannouncement"] != null) & (CommandLine["title"] != null) & (CommandLine["announcement"] != null))
                    {
                      AddAnnouncement(PDUrl, CommandLine["title"], CommandLine["announcement"]); 
                    }      
                    
                //ADD MORE FUNCTIONS HERE!
                    if (CommandLine["meta"] != null)
                    {
                        //FOR TESTING JUNK

                    }
                    if (CommandLine["export"] == "true")
                    {
                        string ExPath = "";
                        bool ExpVersions = false;

                        if (CommandLine["filepath"] != null) { ExPath = CommandLine["filepath"]; }
                        if (CommandLine["includeversions"] == "true") { ExpVersions = true; }

                        ExportFiles(PDUrl, ExPath, ExpVersions);
                    }
                    
                    if ((CommandLine["check"] == "true") & (CommandLine["name"] != null))
                    {
                        Console.Write(CheckForList(PDUrl, CommandLine["name"]));
                    }
                    
                    if ((CommandLine["import"] == "true") & (CommandLine["filepath"] != ""))
                    {
                        string DocLibName = CommandLine["name"];
                        BulkImport(PDUrl, DocLibName, CommandLine["filepath"]);
                    }
                    if ((CommandLine["create"] == "true") & (CommandLine["name"] != null) & (CommandLine["type"] != null))
                    {
                        string _listType = CommandLine["type"];
                        string ListName = CommandLine["name"];
                        Int32 listType = 0;
                        switch (_listType)
                        {
                            case "Generic":
                                { listType = 100; break; }
                            case "Events":
                                { listType = 106; break; }
                            case "DocLibrary":
                                { listType = 101; break; }
                            case "Contacts":
                                { listType = 105; break; }
                            case "Announcements":
                                { listType = 104; break; }
                            case "Links":
                                { listType = 103; break; }
                            case "Discussion":
                                { listType = 108; break; }
                            case "PicLibrary":
                                { listType = 109; break; }
                            case "Tasks":
                                { listType = 107; break; }
                        }
                      CreateNewList(PDUrl, ListName, listType);
                    }

                }
                if (CommandLine["help"] == "true") { GetHelp(); }   
            }


        }
        //Add Other functions here
        public static XmlNode GetListFields(string URL, string dLib)
        {
            PDLists.Lists meta = new PDLists.Lists();
            meta.Credentials = System.Net.CredentialCache.DefaultCredentials;
            meta.Url = URL + "lists.asmx";
            
            XmlNode fieldxml = meta.GetList(dLib);
            XmlDocument Fields = new XmlDocument();

            //Fields.LoadXml(fieldxml.OuterXml);
            Fields.LoadXml("<Fields/>");
            XmlNode _results = Fields.DocumentElement;

            foreach (XmlNode field in fieldxml.ChildNodes)
            {
                if (field.Name == "Fields")
                {
                    foreach (XmlNode mField in field.ChildNodes)
                    {
                        _results.AppendChild(Fields.ImportNode(mField, true));
                    }
                }
            }
            meta.Dispose();
            return _results;
        }
        public static string ListContent(string URL, string Type)
        {
            PDLists.Lists listService = new PDLists.Lists();
            listService.Credentials = System.Net.CredentialCache.DefaultCredentials;
            listService.Url = URL + "lists.asmx";
            string _results = "";

            if (Type == "true")
            {
                try
                {
                    System.Xml.XmlNode lists = listService.GetListCollection();

                    _results = "[displaying content]\n";
                    foreach (XmlNode list in listService.GetListCollection())
                    {
                        string title = list.Attributes["Title"].Value;
                        string listName = list.Attributes["ID"].Value;
                        string listpath = URL.Substring(0, URL.LastIndexOf('/'));
                        string listUrl = list.Attributes["DefaultViewUrl"].Value.Replace("/Forms/AllItems.aspx", string.Empty);
                        char[] seperator = new char[] { '/' };
                        _results = _results + "[object] " + title + " \n [url]" + listpath + listUrl + "\n";
                    }
                }
                catch (Exception ex)
                {
                    _results = ex.Message;
                }
            }
            if (Type == "documents")
            {
                //START
                //string documentLibraryName = @"Document Library";
                string documentLibraryType = "101";
                PDLists.Lists wsList = new PDLists.Lists();
                wsList.Credentials = System.Net.CredentialCache.DefaultCredentials;
                wsList.Url = URL + @"lists.asmx";

                // get a list of all top level lists
                XmlNode allLists = wsList.GetListCollection();

                // load into an XML document so we can use XPath to query content
                XmlDocument allListsDoc = new XmlDocument();
                allListsDoc.LoadXml(allLists.OuterXml);
                XmlNamespaceManager ns = new XmlNamespaceManager(allListsDoc.NameTable);
                ns.AddNamespace("d", allLists.NamespaceURI);

                //XmlNode dlNode = allListsDoc.SelectSingleNode("/d:Lists/d:List[@ServerTemplate='" + documentLibraryType + "']", ns);
                //if (dlNode == null)
                //{ Console.WriteLine(" document library '{0}' not found!", documentLibraryType); }
                //else
                //{

            XmlNodeList rsNodes = allListsDoc.SelectNodes("/d:Lists/d:List[@ServerTemplate='" + documentLibraryType + "']", ns);
            foreach (XmlNode rsItem in rsNodes)
            {

                if (rsNodes == null)
                { Console.WriteLine(" document library '{0}' not found!", documentLibraryType); }
                else
                {
                    // obtain the GUID for the document library and the webID
                    string documentLibraryGUID = rsItem.Attributes["ID"].Value;
                    string documentLibraryName = rsItem.Attributes["Title"].Value;

                    Console.WriteLine(" document library has label of '{0}'", documentLibraryName);
                    Console.WriteLine(" document library has GUID of   {0}", documentLibraryGUID);
                    //Console.WriteLine("\n directory of " + CommandLine["url"] + "\n");

                    // create ViewFields CAML
                    XmlDocument viewFieldsDoc = new XmlDocument();

                    XmlNode ViewFields = AddXmlElement(viewFieldsDoc, "ViewFields", "");
                    AddFieldRef(ViewFields, "GUID");
                    AddFieldRef(ViewFields, "ContentType");
                    AddFieldRef(ViewFields, "BaseName");
                    AddFieldRef(ViewFields, "Modified");
                    AddFieldRef(ViewFields, "EncodedAbsUrl");

                    XmlDocument queryOptionsDoc = new XmlDocument();
                    XmlNode QueryOptions = AddXmlElement(queryOptionsDoc, "QueryOptions", "");
                    AddXmlElement(QueryOptions, "Folder", documentLibraryName);
                    XmlNode node = AddXmlElement(QueryOptions, "ViewAttributes", "");
                    AddXmlAttribute(node, "Scope", "Recursive");
                    //queryOptionsDoc.Save(@"c:\queryOptions.xml"); // for debug
                    System.Xml.XmlElement query = queryOptionsDoc.CreateElement("Query");
                    System.Xml.XmlElement viewFields = queryOptionsDoc.CreateElement("ViewFields");
                    //System.Xml.XmlElement queryOptions = queryOptionsDoc.CreateElement("QueryOptions");

                    // obtain the list of items in the document library
                    XmlNode listContent = wsList.GetListItems(documentLibraryGUID, null, query, viewFields, null, QueryOptions);
                    XmlDocument xmlResultsDoc = new XmlDocument();
                    xmlResultsDoc.LoadXml(listContent.OuterXml);
                    ns = new XmlNamespaceManager(xmlResultsDoc.NameTable);
                    ns.AddNamespace("z", "#RowsetSchema");

                    // xmlResultsDoc.Save(@"c:\listContent.xml"); // for debug
                    XmlNodeList rows = xmlResultsDoc.SelectNodes("//z:row", ns);
                    if (rows.Count == 0)
                    {
                        Console.WriteLine("no content found");
                    }
                    foreach (XmlNode row in rows)
                    {
                        //File.AppendAllText(@"c:\test\export.xml" , row.OuterXml);
                        _results = _results + row.Attributes["ows_Modified"].Value + "      " + row.Attributes["ows_LinkFilename"].Value + "\n";
                        //SHOW ALL ATTRIBUTES FOR DEBUG
                        //foreach (XmlAttribute attrib in row.Attributes)
                        //{
                            //Console.Write(attrib.Name + ": " + attrib.Value + "\n");
                        //}

                    }
                }

                    //END
                }
                wsList.Dispose();
                
            }
            listService.Dispose();
            
            return _results;
                            
        }
        public static XmlNamespaceManager GetXmlNameSpace(XmlNameTable inputTable)
        {
            XmlNamespaceManager xs = new XmlNamespaceManager(inputTable);

            return xs;
        }
        
        //XML Functions

        public static XmlNode AddXmlElement(XmlNode parent, string elementName, string elementValue)
{
    XmlNode element = parent.AppendChild(parent.OwnerDocument.CreateNode(XmlNodeType.Element, elementName, ""));
    if (elementValue != "")
        element.InnerText = elementValue;
    return (element);
}
        public static XmlNode AddXmlElement(XmlDocument parent, string elementName, string elementValue)
{
XmlNode element = parent.AppendChild(parent.CreateNode(XmlNodeType.Element, elementName, ""));
    if (elementValue != "")
element.InnerText = elementValue;
return (element);
}
        public static XmlNode AddXmlAttribute(XmlNode element, string attrName, string attrValue)
{

    XmlNode attr = element.Attributes.Append((XmlAttribute)element.OwnerDocument.CreateNode(XmlNodeType.Attribute, attrName, ""));

    if (attrValue != "")

        attr.Value = attrValue;

    return (attr);

}
        public static XmlNode GetVersions(string ServerLinkUrl, string PDUrl)
        {
            XmlDocument xmlDoc = new System.Xml.XmlDocument();
            xmlDoc.LoadXml("<version />");
            XmlNode _results = xmlDoc.DocumentElement;

            try
            {
                PDVersions.Versions DocVers = new PDVersions.Versions();
                DocVers.Credentials = System.Net.CredentialCache.DefaultCredentials;
                DocVers.Url = PDUrl + "versions.asmx";
                XmlNode vers = DocVers.GetVersions(ServerLinkUrl);
                foreach (XmlNode verItem in vers.ChildNodes)
                {
                    if (verItem.Name.Equals("result"))
                    {
                        _results.AppendChild(xmlDoc.ImportNode(verItem, true));
                    }
                }
                DocVers.Dispose();
            }
            catch (System.Web.Services.Protocols.SoapException ex)
            {
                Console.WriteLine("Message:\n" + ex.Message + "\nDetail:\n" + ex.Detail.InnerText + "\nStackTrace:\n" + ex.StackTrace);
                Console.WriteLine("link: " + ServerLinkUrl + " url:" + PDUrl);
            }
            return _results;
        }
        public static void AddFieldRef(XmlNode viewFields, string fieldName)
{
    XmlNode fieldRef = AddXmlElement(viewFields, "FieldRef", "");
    AddXmlAttribute(fieldRef, "Name", fieldName);
}

        //SHAREPOINT FUNCTIONS
        public static void ExportFiles(string URL, string FilePath, bool Versions)
        {
            string documentLibraryType = "101";
            PDLists.Lists wsList = new PDLists.Lists();
            wsList.Credentials = System.Net.CredentialCache.DefaultCredentials;
            wsList.Url = URL + @"lists.asmx";

            try
            {
                XmlNode allLists = wsList.GetListCollection();
                XmlDocument allListsDoc = new XmlDocument();
                allListsDoc.LoadXml(allLists.OuterXml);

                //Create Name Space Manager
                XmlNamespaceManager ns = GetXmlNameSpace(allListsDoc.NameTable);
                ns.AddNamespace("d", allLists.NamespaceURI);

                XmlNodeList rsNodes = allListsDoc.SelectNodes("/d:Lists/d:List[@ServerTemplate='" + documentLibraryType + "']", ns);

                string FileMeta = "";
                string MetaFile = FilePath + "/manifest.xml";
                if (File.Exists(MetaFile))
                {
                    File.Delete(MetaFile);
                }

                Directory.CreateDirectory(FilePath);
                FileMeta = "<Export>\n";

                //FOR EACH DOCUMENT LIBRARY
                String DocLibFields = "";
                foreach (XmlNode rsItem in rsNodes)
                {
                    string documentLibraryGUID = rsItem.Attributes["ID"].Value;
                    string documentLibraryName = rsItem.Attributes["Title"].Value;

                    DocLibFields += "<Document_Library name=\"" + documentLibraryName + "\">\n" + GetListFields(URL, documentLibraryName).OuterXml + "\n</Document_Library>\n";
                    FileMeta += DocLibFields;
                    XmlDocument viewFieldsDoc = new XmlDocument();

                    XmlNode ViewFields = AddXmlElement(viewFieldsDoc, "ViewFields", "");
                    AddFieldRef(ViewFields, "GUID");
                    AddFieldRef(ViewFields, "ContentType");
                    AddFieldRef(ViewFields, "BaseName");
                    AddFieldRef(ViewFields, "Modified");
                    AddFieldRef(ViewFields, "EncodedAbsUrl");

                    XmlDocument queryOptionsDoc = new XmlDocument();
                    XmlNode QueryOptions = AddXmlElement(queryOptionsDoc, "QueryOptions", "");
                    AddXmlElement(QueryOptions, "Folder", documentLibraryName);
                    //AddXmlElement(QueryOptions, "IncludeMandatoryColumns", "FALSE");
                    XmlNode node = AddXmlElement(QueryOptions, "ViewAttributes", "");
                    AddXmlAttribute(node, "Scope", "Recursive");
                    //  for debug
                    queryOptionsDoc.Save(@"c:\queryOptions.xml"); // for debug


                    XmlElement query = queryOptionsDoc.CreateElement("Query");
                    XmlElement viewFields = queryOptionsDoc.CreateElement("ViewFields");

                    XmlNode listContent = wsList.GetListItems(documentLibraryGUID, null, query, viewFields, "500000", QueryOptions);
                    //XmlNode listContent = wsList.GetListItems(documentLibraryGUID, null, null, ViewFields, null, QueryOptions);

                    XmlDocument xmlResultsDoc = new XmlDocument();
                    xmlResultsDoc.LoadXml(listContent.OuterXml);

                    ns = new XmlNamespaceManager(xmlResultsDoc.NameTable);
                    ns.AddNamespace("z", "#RowsetSchema");

                    XmlNodeList rows = xmlResultsDoc.SelectNodes("//z:row", ns);
                    if (rows.Count == 0)
                    {
                        Console.WriteLine("[no content found in library]");
                    }

                    decimal FileCount = rows.Count;
                    decimal FileNum = 0;
                    decimal PercentDone = 0;
                    string ShowPercent = "";
                    string CleanUrl = URL.Replace("/_vti_bin", "");

                    //Row = file
                    foreach (XmlNode row in rows)
                    {
                        FileNum = FileNum + 1;
                        PercentDone = decimal.Round((FileNum / FileCount) * 100, 0);
                        ShowPercent = PercentDone + "% ";

                        if (FilePath != "")
                        {
                            FileMeta = FileMeta + "<File name=\"" + row.Attributes["ows_LinkFilename"].Value + "\" DocLib=\"" + documentLibraryName + "\">\n";

                            //VERSIONS START
                            if (Versions == true)
                            {
                                FileMeta = FileMeta + " <Versions>\n";

                                char[] sep = { ',' };
                                XmlNode mversions = GetVersions(row.Attributes["ows_ServerUrl"].Value, URL);

                                foreach (XmlNode item in mversions.ChildNodes)
                                {
                                    string newDir = item.Attributes["url"].Value.Replace(CleanUrl, "");
                                    newDir = @"\" + newDir.Substring(0, newDir.LastIndexOf("/")) + @"\";
                                    newDir = newDir.Replace("/", @"\");

                                    //Version Number item.Attributes["version"].Value);
                                    //URL item.Attributes["url"].Value);
                                    //Date Created item.Attributes["created"].Value);
                                    //Created By item.Attributes["createdBy"].Value);

                                    FileMeta = FileMeta + " <version number=\"" + item.Attributes["version"].Value + "\"\n";
                                    FileMeta = FileMeta + " server_url=\"" + item.Attributes["url"].Value + "\"\n";
                                    FileMeta = FileMeta + " file_url=\"" + FilePath + newDir + row.Attributes["ows_LinkFilename"].Value + "\" />\n";

                                    Directory.CreateDirectory(FilePath + newDir);
                                    Console.WriteLine("[exporting version] " + row.Attributes["ows_LinkFilename"].Value);
                                    DownloadFile(row.Attributes["ows_EncodedAbsUrl"].Value, FilePath + newDir + row.Attributes["ows_LinkFilename"].Value, 0);
                                    Console.WriteLine("[" + ShowPercent + " done with library]");
                                }

                                FileMeta = FileMeta + " </Versions>\n";
                                //VERSIONS END
                            }
                            //IF (from command line) VERSIONS = FALSE
                            else
                            {
                                FileMeta = FileMeta + " <Versions>\n";

                                string CleanURL = URL.Replace("/_vti_bin/", "").ToUpper();  //URL TO SITE COLLECTION TOP LEVEL
                                string CleanFile = row.Attributes["ows_LinkFilename"].Value.Replace(" ", "%20").ToUpper();  //FILE NAME IN CAPS
                                string CleanPath = row.Attributes["ows_EncodedAbsUrl"].Value.Replace(CleanURL, "").ToUpper();  //FILE PATH NO URL
                                CleanPath = CleanPath.Replace(CleanFile, "");
                                CleanPath = CleanPath.Replace(CleanURL, "").ToLower();
                                CleanPath = CleanPath.Replace("%20", " ");
                                CleanPath = CleanPath.Replace("/", @"\");
                                string newDir = FilePath + CleanPath;

                                FileMeta = FileMeta + " <version number=\"@1\" \n";
                                FileMeta = FileMeta + " server_url=\"" + row.Attributes["ows_EncodedAbsUrl"].Value + "\"\n";
                                FileMeta = FileMeta + " file_url=\"" + newDir + row.Attributes["ows_LinkFilename"].Value + "\" />\n";

                                Directory.CreateDirectory(newDir);
                                Console.WriteLine("[exporting] " + row.Attributes["ows_LinkFilename"].Value);
                                if (File.Exists(newDir + row.Attributes["ows_LinkFilename"].Value) == false)
                                {
                                    DownloadFile(row.Attributes["ows_EncodedAbsUrl"].Value, newDir + row.Attributes["ows_LinkFilename"].Value, 0);
                                }
                                Console.WriteLine("[" + ShowPercent + " done with library]");

                                FileMeta = FileMeta + " </Versions>\n";
                            }
                        }

                        //ADD LOOP HERE FOR ALL ATTRIBUTES
                        //SHOW ALL ATTRIBUTES FOR DEBUG
                        FileMeta = FileMeta + " <Metadata>\n";
                        foreach (XmlAttribute attrib in row.Attributes)
                        {
                            //Clean Meta Data
                            string Attrib_Val = attrib.Value;
                            char[] dirty = { '#' };
                            char[] amp = { '&' };
                            char[] gorl = { '<' };
                            char[] ogre = { '>' };

                            if (Attrib_Val.IndexOfAny(dirty) > 0)
                            {
                                Attrib_Val = Right(attrib.Value, (attrib.Value.Length - attrib.Value.IndexOf("#") - 1));
                            }
                            if (Attrib_Val.IndexOfAny(amp) > 0)
                            {
                                Attrib_Val = Attrib_Val.Replace("&", "&amp;");
                            }
                            Attrib_Val = SecurityElement.Escape(Attrib_Val);

                            FileMeta = FileMeta + "  <" + attrib.Name + ">" + Attrib_Val + "</" + attrib.Name + ">\n";
                        }
                        FileMeta = FileMeta + " </Metadata>\n</File>\n";

                        File.AppendAllText(MetaFile, FileMeta);
                        FileMeta = "";
                    }

                }
                File.AppendAllText(MetaFile, "</Export>");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + ex.StackTrace.ToString());
            }
        }
        public static string GetStructure(string PDUrl)
        {
            PDWebs.Webs WebService = new PDWebs.Webs();
            WebService.Credentials = CredentialCache.DefaultCredentials;
            WebService.Url = PDUrl + "webs.asmx";
            string sitelist = "";

            try
            {
                XmlNode sites = WebService.GetWebCollection();
            }
            catch (SoapException ex)
            {
                Console.WriteLine("Message:\n" + ex.Message + "\nDetail:\n" + ex.Detail.InnerText + "\nStackTrace:\n" + ex.StackTrace);
            }
            foreach (XmlNode site in WebService.GetWebCollection())
            {
                sitelist = sitelist += site.Attributes["Url"].Value + "\n";
            }
            return sitelist;
        }
        public static void GetHelp()
        {
            string syntax = "\npdConsole Tool coded by Michael Coleman. 2007.  ";
            syntax += "\n==========================================================================";
            syntax += "\nPDCONSOLE [/url:] [/structure] [/content[[:]Attributes]] [/export]\n";
            syntax += "  [/filepath[[:]drive:path]] [/includeversions] [/addannouncement   \n";
            syntax += "  [[/title:'<TITLE>'] [/announcement:'<ANNOUNCEMENT>']]]            \n";
            syntax += "\n  /structure                  displays structure of site area.    ";
            syntax += "\n  /content                    displays all lists and libraries.   ";
            syntax += "\n  attributes                  all  All Content     documents  All Documents";
            syntax += "\n  /export                     exports document libraries to filesystem.";
            syntax += "\n  /filepath                   required with export.               ";
            syntax += "\n  /includeversions            used with export, includes all file versions.";
            syntax += "\n  /addannouncement            required to add annoucements.       ";
            syntax += "\n   /title:''                  sets announcement title.            ";
            syntax += "\n   /annoucement:''            sets announcement body.             ";
            syntax += "\n==========================================================================\n";
            syntax += "\nFor help call or email Michael Coleman, MColeman@portal-dynamics.com";
            Console.WriteLine(syntax);
        }
        public static void AddAnnouncement(string PDUrl, string addtitle, string addbody)
        {
            try
            {
                PDLists.Lists AddtoList = new PDLists.Lists();
                AddtoList.Credentials = CredentialCache.DefaultCredentials;
                AddtoList.Url = PDUrl + "lists.asmx";

                XmlDocument doc = new System.Xml.XmlDocument();
                XmlElement batchElement = doc.CreateElement("Batch");
                XmlNode newItemhome = AddtoList.GetListCollection();
                string NewHome = null;
                bool not_exist = false;
                foreach (XmlNode home in AddtoList.GetListCollection())
                {
                    string title = home.Attributes["Title"].Value;
                    string listName = home.Attributes["ID"].Value;
                    string roothome = "Announcements";
                    if (title == roothome)
                    {
                        NewHome = listName;
                        not_exist = false;
                    }
                    else { not_exist = true; }
                }
                if (not_exist == true)
                {
                    CreateNewList(PDUrl, "Announcements", 104);
                    //AddtoList.AddList("<i>Announcements</i>", "<i>Announcements</i>", 104);
                }
                batchElement.SetAttribute("OnError", "Continue");
                batchElement.SetAttribute("ListVersion", "1");

                string newAnnoucement = addbody;
                string newtitle = addtitle;

                batchElement.InnerXml = "<Method ID='1' Cmd='New'><Field Name='Title'>" + newtitle + "</Field><Field Name='Body'>" + newAnnoucement + "</Field></Method>";

                AddtoList.UpdateListItems(NewHome, batchElement);
                Console.WriteLine("Success.");

            }
            catch (System.Web.Services.Protocols.SoapException ex)
            {
                Console.WriteLine("Message:\n" + ex.Message + "\nDetail:\n" + ex.Detail.InnerText + "\nStackTrace:\n" + ex.StackTrace);
            }

        }
        public static void BulkImport(string URL, string DocLibName, string FilePath)
        {
            FPSEPublish.FPSEPublish fpse = new FPSEPublish.FPSEPublish();
            string OriginalPath = FilePath;
            string UploadURL = URL.Replace("/_vti_bin/", "/") + DocLibName;
            string historyPath = OriginalPath + @"\_vti_history";

            if (DocLibName != null)
            {
                if (CheckForList(URL, DocLibName) == true)
                {
                    //LIBRARY ALREADY EXISTS, BEGIN CREATING FOLDERS AND COPYING FILES
                    char[] split = { ',' };
                    string[] FileList = GetFilesfromHD(FilePath, FilePath).Split(split);
                    string[] FolderList = GetFoldersfromHD(FilePath, FilePath).Split(split);

                    //CREATE ALL FOLDERS REQUIRED TO UPLOAD ALL THE FILES
                    string strfolder = "";

                    Console.WriteLine("[creating folder structure]");
                    foreach (string folder in FolderList)
                    {
                        if ((folder != "") & (folder.StartsWith("http") == false))
                        {
                            strfolder = folder.Replace(@"\", "/");
                            CreateFolder(URL, DocLibName, strfolder);
                        }
                    }
                    Console.WriteLine("[folder structure created]");
                    Console.WriteLine("[uploading files to Document Library]");

                    foreach (string file in FileList)
                    {
                        try
                        {
                            string logicalfile = FilePath + file;
                            string webfile = UploadURL + file.Replace(@"\", "/");

                            string _folder = webfile.Substring(0, webfile.LastIndexOf("/") + 1);

                            _folder = _folder.Replace(UploadURL, "");
                            _folder = _folder.Replace(URL, "");
                            _folder = _folder.Replace(DocLibName, "");
                            webfile = webfile.Replace(" ", "%20");

                            if (_folder.StartsWith("http") == false)
                            {
                                fpse.PutDocument(webfile, logicalfile, null);
                                Console.WriteLine("[uploaded] " + logicalfile);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }

                    }
                }
                else
                {
                    //LIBRARY DOES NOT EXIST, CREATE LIBRARY AND BEGIN CREATING FOLDERS AND COPYING FILES
                    Console.WriteLine("[creating document library]");
                    CreateNewList(URL, DocLibName, 101);
                    Console.WriteLine("[created document library]");
                    char[] split = { ',' };
                    string[] FileList = GetFilesfromHD(FilePath, FilePath).Split(split);
                    string[] FolderList = GetFoldersfromHD(FilePath, FilePath).Split(split);

                    //CREATE ALL FOLDERS REQUIRED TO UPLOAD ALL THE FILES
                    string strfolder = "";

                    Console.WriteLine("[creating folder structure]");
                    foreach (string folder in FolderList)
                    {
                        if ((folder != "") & (folder.StartsWith("http") == false))
                        {
                            strfolder = folder.Replace(@"\", "/");
                            CreateFolder(URL, DocLibName, strfolder);
                        }
                    }
                    Console.WriteLine("[folder structure created]");
                    Console.WriteLine("[uploading files to Document Library]");

                    foreach (string file in FileList)
                    {
                        try
                        {
                            string logicalfile = FilePath + file;
                            string webfile = UploadURL + file.Replace(@"\", "/");

                            string _folder = webfile.Substring(0, webfile.LastIndexOf("/") + 1);

                            _folder = _folder.Replace(UploadURL, "");
                            _folder = _folder.Replace(URL, "");
                            _folder = _folder.Replace(DocLibName, "");
                            webfile = webfile.Replace(" ", "%20");

                            if (_folder.StartsWith("http") == false)
                            {
                                fpse.PutDocument(webfile, logicalfile, null);
                                Console.WriteLine("[uploaded] " + logicalfile);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                    }
                }
            }

            //  WORK ON THIS FIRST, MULTIPLE DOC LIBS IMPORTANT
            //  NO DOC LIB NAME SPECIFIED CREATE STRUCTURE FROM FOLDER
            else
            {
                char[] split = { ',' };

                if (CheckForManifest(FilePath) == true)  //IF Export manifest exists.
                {

                    XmlDocument Manifest = new XmlDocument();
                    XmlTextReader ImportManifest = new XmlTextReader(FilePath + @"\manifest.xml");
                    XmlNamespaceManager nsManifest = new XmlNamespaceManager(ImportManifest.NameTable);

                    string fName;
                    string dLib;
                    string nFolder;
                    string nFile;
                    char[] slash = { '/' };
                    string LastOne = "";
                    
                    ImportManifest.Read();
                    Manifest.Load(ImportManifest);

                    Console.WriteLine("[creating structure]");
                    Console.WriteLine("[creating document libraries]");

                    //GET AND UPDATE ALL LIST FIELDS / COLUMNS
                    //XmlNode ndFields = GetListFields(URL, dLib);  //THIS IS WRONG NEED FROM FILE!
                    XmlNodeList Libraries = Manifest.SelectNodes("/Export/Document_Library");

                    foreach (XmlNode Library in Libraries)
                    {
                        // CREATE DOC LIB HERE
                        if (CheckForList(URL, Library.Attributes["name"].Value) == false)
                        {
                            Console.WriteLine("[creating document library] " + Library.Attributes["name"].Value);
                            CreateNewList(URL, Library.Attributes["name"].Value, 101);
                        }

                        //GET LIST META FIELDS AND UPDATE
                        foreach (XmlNode Field in Library)
                        {
                            Console.WriteLine(Field.InnerXml);
                        }

                    }


                    //END LIST UPDATE

                    XmlNodeList Export = Manifest.SelectNodes("/Export/File", nsManifest);  // Node list of all Files
                    foreach (XmlNode Files in Export)  // Break down per file
                    {
                        fName = Files.Attributes["name"].Value;
                        dLib = Files.Attributes["DocLib"].Value;

                        //GET ALL FILE METADATA
                        XmlNode MetaData = Manifest.SelectSingleNode("/Export/File[@name=\"" + fName + "\"]/Metadata");
                        string UpdateFields = "";
                        foreach (XmlElement mField in MetaData)
                        {
                            //Console.WriteLine(mField.Name);
                            string NewName = mField.Name.Replace("ows_", "");
                            if (NewName != "ID")
                            {
                                UpdateFields += "<Field name = '" + NewName + "'>" + mField.InnerText + "</Field>";
                            }
                        }
                        //Console.WriteLine(UpdateFields);

                        nFolder = Manifest.SelectSingleNode("/Export/File[@name=\"" + fName + "\"]/Metadata/ows_FileDirRef").InnerText;
                        nFolder = nFolder.Substring((nFolder.IndexOf(dLib) + dLib.Length));

                        //Console.WriteLine(UpdateFields);
                        //Console.WriteLine("[creating folder structure]");
                        string folderstruc = "";
                        if (nFolder != "")
                        {
                            if (nFolder.LastIndexOf("/") > 0)
                            {
                                //Create more than 1
                                string[] multi = nFolder.Split(slash);
                                string root = "/" + multi[1];
                                CreateFolder(URL, dLib, root);

                                for (int i = 2; i <= multi.GetUpperBound(0); i++)
                                {
                                    folderstruc += "/" + multi[i] + "/";
                                    CreateFolder(URL, dLib, root + "/" + folderstruc);
                                }
                            }
                            if (nFolder != LastOne)
                            {
                                CreateFolder(URL, dLib, nFolder);
                            }
                            LastOne = nFolder;
                        }
                        //END METADATA

                        //FOLDER STRUCTURE AND DOCUMENT LIBRARIES ARE CREATED BY NOW, UPLOAD FILES!
                        nFile = Manifest.SelectSingleNode("/Export/File[@name=\"" + fName + "\"]/Metadata/ows_FileRef").InnerText;
                        nFile = nFile.Substring((nFile.IndexOf(dLib) + dLib.Length));
                        nFile = nFile.Replace(" ", "%20");
                        string Up2Url = URL.Replace("_vti_bin/", "");

                        string NewLoc = Up2Url + dLib + nFile;

                        //GET A LIST OF VERSIONS FOR UPLOAD
                        XmlNode VerList = Manifest.SelectSingleNode("/Export/File[@name=\"" + fName + "\"]/Versions"); //Get Versions of current file
                        int VerCount = VerList.ChildNodes.Count;
                        if (VerCount > 1)
                        {
                            for (int x = 1; x <= VerCount; x++)
                            {
                                string ver = "";
                                if (x == VerCount)
                                {
                                    ver = "@" + x.ToString();
                                }
                                else
                                {
                                    ver = x.ToString();
                                }
                                XmlNode Multi = Manifest.SelectSingleNode("/Export/File[@name=\"" + fName + "\"]/Versions/version[@number=\"" + ver + "\"]");
                                fpse.PutDocument(NewLoc, Multi.Attributes["file_url"].Value, null);
                                Console.WriteLine("[uploaded version] " + fName);
                                if (UpdateFile(URL, fName, dLib, UpdateFields) == "TRUE")
                                { Console.WriteLine("[meta data updated]"); }
                            }
                        }
                        else
                        {
                            XmlNode Single = Manifest.SelectSingleNode("/Export/File[@name=\"" + fName + "\"]/Versions/version[@number=\"@1\"]");
                            fpse.PutDocument(NewLoc, Single.Attributes["file_url"].Value, null);
                            Console.WriteLine("[uploaded] " + fName);
                            if (UpdateFile(URL, fName, dLib, UpdateFields) == "TRUE")
                            { Console.WriteLine("[meta data updated]"); }
                        }
                    }
                }
                else  //IF Export Manifest does not exist.
                {
                    Console.WriteLine("no manifest, making some junk up....");
                }
            }
        }
        public static string ListName2GUID(string URL, string dLibName)
        {
            PDLists.Lists GetGUID = new PDLists.Lists();
            GetGUID.Credentials = CredentialCache.DefaultCredentials;
            XmlNode List = GetGUID.GetListCollection();
            string _result = "";
            foreach (XmlNode list in List)
            {
                if (list.Attributes["Title"].Value == dLibName) 
                { _result = list.Attributes["ID"].Value; }
            }

            return _result;
        }
        public static string UpdateFile(string sSPURL, string sFileName, string sDocLib, string sFieldInfo)
        {
            PDLists.Lists UpdateList = new PDLists.Lists();
            UpdateList.Credentials = System.Net.CredentialCache.DefaultCredentials;
            UpdateList.Url = sSPURL + "lists.asmx";

            string sFileIDinList = "";
            string strBatch;
            //string sFinalFilePath;
            string sListID = "";

            //sSiteDoc = sSiteDoc.Replace("%20", " ");
            //sSiteDoc = sSiteDoc.Replace(@"\", "/");

            XmlDocument xml = new XmlDocument();
            try
            {
                //FIND ID OF LIST
                foreach (XmlNode col in UpdateList.GetListCollection())
                {
                    if (col.Attributes["Title"].Value == sDocLib)
                    { sListID = col.Attributes["ID"].Value; }
                }


                XmlDocument viewFieldsDoc = new XmlDocument();

                XmlNode ViewFields = AddXmlElement(viewFieldsDoc, "ViewFields", "");
                AddFieldRef(ViewFields, "GUID");
                AddFieldRef(ViewFields, "ContentType");
                AddFieldRef(ViewFields, "BaseName");
                AddFieldRef(ViewFields, "Modified");
                AddFieldRef(ViewFields, "EncodedAbsUrl");

                XmlDocument queryOptionsDoc = new XmlDocument();
                XmlNode QueryOptions = AddXmlElement(queryOptionsDoc, "QueryOptions", "");
                AddXmlElement(QueryOptions, "Folder", sDocLib);
                XmlNode node = AddXmlElement(QueryOptions, "ViewAttributes", "");
                AddXmlAttribute(node, "Scope", "Recursive");
                XmlElement query = queryOptionsDoc.CreateElement("Query");
                XmlElement viewFields = queryOptionsDoc.CreateElement("ViewFields");
                XmlNode listContent = UpdateList.GetListItems(sListID, null, query, viewFields, null, QueryOptions);

                foreach (XmlNode item in listContent)
                {
                    Console.WriteLine("made it here" + item.Attributes["ows_LinkFilename"].Value);
                    if (item.Attributes["ows_LinkFilename"].Value == sFileName)
                    { sFileIDinList = item.Attributes["ID"].Value; }

                }

                if (sFileIDinList != null)
                {
                    strBatch = "<Method ID='1' Cmd='Update'>";
                    //strBatch += "<Field Name = '"+sField+"'>" + sValue  + "</Field>";
                    strBatch += sFieldInfo;
                    strBatch += "</Method>";

                    XmlElement elBatch = xml.CreateElement("Batch");
                    elBatch.InnerXml = strBatch;
                    XmlNode ndreturn = UpdateList.UpdateListItems(sListID, elBatch);
                }
                return "TRUE";

            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }
        public static string UpdateList(string URL, string List, string nFields, string uFields)
        {
            PDLists.Lists Update = new PDLists.Lists();
            Update.Credentials = CredentialCache.DefaultCredentials;
            Update.Url = URL + "lists.asmx";

            XmlNode ndList = Update.GetList(List);
            XmlNode ndVersion = ndList.Attributes["Version"];

            XmlDocument xmlDoc = new XmlDocument();

            XmlNode ndUpdateFields = xmlDoc.CreateNode(XmlNodeType.Element, "Fields", "");
            XmlNode ndNewFields = xmlDoc.CreateNode(XmlNodeType.Element, "Fields", "");

            string ListGUID = ListName2GUID(URL, List);

            ndNewFields.InnerXml = nFields;
            ndUpdateFields.InnerXml = uFields;

            try
            {
                XmlNode ndReturn = Update.UpdateList(ListGUID, null, ndNewFields, ndUpdateFields, null, null);
            }
            catch(Exception ex)
            {
                return ex.Message;
            }
            return "[updated fields]";

        }
        public static void EnableVersioning(string URL, string ListName)
        {
            PDLists.Lists EnableVersions = new PDLists.Lists();
            EnableVersions.Credentials = CredentialCache.DefaultCredentials;
            EnableVersions.Url = URL + "lists.asmx";

            XmlNode _response = null;

            XmlNode ndList = EnableVersions.GetList(ListName);
            XmlNode ndVersion = ndList.Attributes["Version"];

            XmlDocument xmlDoc = new System.Xml.XmlDocument();

            XmlNode ndProperties = xmlDoc.CreateNode(XmlNodeType.Element, "List", "");
            XmlAttribute ndVersionAttrib = (XmlAttribute)xmlDoc.CreateNode(XmlNodeType.Attribute, "EnableVersioning", "");
            ndVersionAttrib.Value = "TRUE";

            ndProperties.Attributes.Append(ndVersionAttrib);

            XmlDocument doc = new System.Xml.XmlDocument();
            XmlElement batchElement = doc.CreateElement("Batch");
            XmlNode newItemhome = EnableVersions.GetListCollection();

            try
            {
                _response = EnableVersions.UpdateList(ndList.Attributes["ID"].Value, ndProperties, null, null, null, ndVersion.Value);

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + "\n " + ex.StackTrace);

            }
            Console.WriteLine("[versioning enabled]");

        }
        
        //WEB FUNCTIONS
        public static void DownloadFile(string fileURL, string fileName, Int32 Retry)
        {
           try
            {
               WebClient filedownload = new WebClient();
               filedownload.Credentials = CredentialCache.DefaultCredentials;
               filedownload.DownloadFile(fileURL, fileName);
            }
            catch(Exception exp)
            {
                if (Retry < 10)
                {
                    Console.WriteLine("[error downloading] " + fileURL + "\n  [-retrying " + Retry + " out of 10.]");
                    Retry = Retry + 1;
                    DownloadFile(fileURL, fileName, Retry);
                }
                else
                {
                    Console.WriteLine("[cannot download] " + fileURL + "\n" + exp.Message);
                }
                
            }
        }
        public static void UploadFile(string FileURL, string FileSRC)
        {
            FileInfo fileInfo = new FileInfo(FileSRC);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(FileURL);
            request.Credentials = CredentialCache.DefaultCredentials;
            request.Method = "PUT";
            Stream requestStream = request.GetRequestStream();
            StreamWriter writer = new StreamWriter(requestStream);
            FileStream sourceFile = fileInfo.OpenRead();
            byte[] buffer = new byte[sourceFile.Length];
            sourceFile.Read(buffer, 0, buffer.Length);
            writer.Write(buffer);
            sourceFile.Close();
            writer.Close();

            try
            {
                WebResponse response = request.GetResponse();
                response.Close();
            }
            catch (WebException)
            {
               Console.WriteLine("File: " + request.RequestUri.ToString() +
                    "\n\nCould not be created.");
            }

        }
        public static void CreateFolder(string URL, string DocLibName, string NewFolder)
        {
            try
            {
                PDDws.Dws DWSService = new PDDws.Dws();
                DWSService.Credentials = CredentialCache.DefaultCredentials;
                DWSService.Url = URL + "dws.asmx";
                string strResults = "";
                if (NewFolder != "")
                {
                string Folder = NewFolder;
                strResults = DWSService.CreateFolder(DocLibName + Folder);
                if (strResults == "<Result/>")
                {
                    Console.WriteLine("[created] " + Folder);
                }
                if (strResults.Contains("13"))
                {
                    //Console.WriteLine("[exists] " + Folder);
                }
                }
            }
            catch(Exception exc)
            {
                Console.WriteLine(exc.Message);
            }
            
        }

        //DONT THINK I WILL NEED THESE ANYMORE...  OR WAIT, FOR WITHOUT MANIFEST
        public static string GetFilesfromHD(string filepath, string RootDir)
        {
            string fileoutput = "";
            //filepath = filepath.Replace(",", "");
            string[] fileEntries = Directory.GetFiles(filepath);
            
            foreach (string fileName in fileEntries)
            {
               fileoutput = fileoutput + fileName + ",";
            }
           
            string dumpoutput = fileoutput.Replace(RootDir, "");
            
            string[] subdirEntries = Directory.GetDirectories(filepath);
                        
            foreach (string subdir in subdirEntries)
            {
                if ((File.GetAttributes(subdir) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint)
                {
                    dumpoutput = dumpoutput + GetFilesfromHD(subdir, RootDir);
                }
            }
           return dumpoutput;
        }
        public static string GetFoldersfromHD(string filepath, string RootDir)
        {
            string folderoutput = "";

            string[] subdirEntries = Directory.GetDirectories(filepath);
            foreach (string folder in subdirEntries)
            {
                folderoutput = folderoutput + folder + ",";
            }
            string dumpoutput = folderoutput.Replace(RootDir, "");

            foreach (string subdir in subdirEntries)
            {
                //if ((File.GetAttributes(subdir) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint)
                //{
                    dumpoutput = dumpoutput + GetFoldersfromHD(subdir, RootDir);
                //}
            }
            return dumpoutput;
        }
        public static string FormatLibName(string inputName)
        {
            string _temp = "";
            if (inputName.Length > 0)
            {
                try
                {
                    _temp = inputName;
                    
                    string _tempLeft = "";
                    string _tempRight = "";
                    char[] space = { ' ' };

                    if (_temp.IndexOfAny(space) > 0)
                    {
                        _tempLeft = _temp.Substring(0, _temp.IndexOf(" "));
                        _tempRight = _temp.Substring((_tempLeft.Length + 1));
                        
                        Char[] letters = _tempRight.ToCharArray();
                        letters[0] = Char.ToUpper(letters[0]);
                        string _Right = new string(letters);

                        _temp = _temp.Replace(_tempLeft, _tempLeft.ToUpper());
                        _temp = _temp.Replace(_tempRight, _Right);
                    }
                    else
                    {
                        //string _toUpper = _tempLeft.Substring(0, 1);
                        _temp = _temp.Substring(0, 1).ToUpper() + _temp.Substring(1);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            return _temp;
        }
        public static string FoldertoDocLib(string filepath, string RootDir)
        {
            string folderoutput = "";
            string[] subdirEntries = Directory.GetDirectories(filepath);
            foreach (string folder in subdirEntries)
            {
                folderoutput = folderoutput + folder + ",";
            }
            string dumpoutput = folderoutput.Replace(RootDir, "");

            dumpoutput = dumpoutput.Replace(@",\_vti_history", "");
            dumpoutput = dumpoutput.Replace(@"\", "");

            return dumpoutput;
        }
        public static void CreateNewList(string URL, string Name, Int32 Type)
        {
            PDLists.Lists CreateList = new PDLists.Lists();
            CreateList.Credentials = CredentialCache.DefaultCredentials;
            CreateList.Url = URL + "lists.asmx";

            try
            {
                CreateList.AddList(Name, Name, Type);
                //ENABLE VERSIONING ON DOC LIBS
                if (Type == 101)
                {
                    EnableVersioning(URL, Name);
                }
            }
            catch (System.Web.Services.Protocols.SoapException ex)
            {
                Console.WriteLine("Message:\n" + ex.Message + "\nDetail:\n" + ex.Detail.InnerText + "\nStackTrace:\n" + ex.StackTrace);
                
            }
        }
        public static bool CheckForList(string Url, string ListName)
        {
            PDLists.Lists CheckList = new PDLists.Lists();
            CheckList.Credentials = CredentialCache.DefaultCredentials;
            CheckList.Url = Url + "lists.asmx";

            bool exist = false;

            foreach (XmlNode home in CheckList.GetListCollection())
            {
                string title = home.Attributes["Title"].Value;
                if (title == ListName)
                {
                   exist = true;
                   break;
                }
            }
            return exist;
        }
        public static bool CheckForManifest(string path)
        {
            if (File.Exists(path + @"\manifest.xml"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        
        //MY CRAZY STRING FUNCTIONS
        public static string Right(string param, int length)
        {
            string result = param.Substring(param.Length - length, length);
            return result;
        }
        public static string Left(string param, int length)
        {
            string result = param.Substring(0, length);
            return result;
        }
        public static string CleanString(string strIn)
        {
            //replace invalid characters with blank space
            return Regex.Replace(strIn, @"^\w\<>", "");
        }

    }
}